package com.boge.parse.web;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

/**
 * @author boge
 *
 */
public class WebSocketUtils {
    
	static final String SessionAttribute = "isWEB";
	
	static final String VERSION = "0.1.4";
	static final int TOKEN_LENGHT = 16;
	public static String key = null;
	static final String path = "/";
    /** 服务器返回的头 */
	public static Map<String, String> header;
    public static String GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
	
    // Construct a successful websocket handshake response using the key param
    // (See RFC 6455).
	public static WebSocketHandShakeResponse buildWSHandshakeResponse(String key){
        String response = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n";
        response += "Upgrade: websocket\r\n";
        response += "Connection: Upgrade\r\n";
        response += "Sec-WebSocket-Accept: " + key + "\r\n";
        response += "\r\n";        
        return new WebSocketHandShakeResponse(response);
    }
    
    // Parse the string as a websocket request and return the value from
    // Sec-WebSocket-Key header (See RFC 6455). Return empty string if not found.
	public static String getClientWSRequestKey(String WSRequest) {
        String[] headers = WSRequest.split("\r\n");
        String socketKey = "";
        for (int i = 0; i < headers.length; i++) {
            if (headers[i].contains("Sec-WebSocket-Key")) {
                socketKey = (headers[i].split(":")[1]).trim();
                break;
            }
        }
        return socketKey;
    }    
    
    // 
    // Builds the challenge response to be used in WebSocket handshake.
    // First append the challenge with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" and then
    // make a SHA1 hash and finally Base64 encode it. (See RFC 6455)
	public static String getWebSocketKeyChallengeResponse(String challenge) throws NoSuchAlgorithmException, UnsupportedEncodingException {

        challenge += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
        MessageDigest cript = MessageDigest.getInstance("SHA-1");
        cript.reset();
        cript.update(challenge.getBytes("utf8"));
        byte[] hashedVal = cript.digest();
        return Base64.encodeBase64String(hashedVal);
    }

	/**
	 * 创建头部消息
	 */
	public static String createHeader(String host, int port) {
		if (key == null) {
			key = generateToken(TOKEN_LENGHT);
		}
        if (host == "127.0.0.1" || host == "0.0.0.0") {
            host = "localhost";
        }
        String origin = "null";
        return
            "GET "+path+" HTTP/1.1"+"\r\n" +
            "Origin: "+origin+"\r\n" +
            "Host: "+host+":"+port+"\r\n" +
            "Sec-WebSocket-Key: "+key+ "\r\n" +
            "User-Agent: PHPWebSocketClient/" + VERSION + "\r\n" +
            "Upgrade: websocket" + "\r\n" +
            "Connection: Upgrade" + "\r\n" +
            "Sec-WebSocket-Protocol: wamp" + "\r\n" +
            "Sec-WebSocket-Version: 13" + "\r\n" + "\r\n";
    }

	private static String generateToken(int length) {
		String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"§$%&/()=[]{}";
        List<String> useChars = new ArrayList<>();
        // select some random chars:
        Random random = new Random();
        for (int i = 0; i < length; i++) {
        	useChars.add(String.valueOf(characters.charAt(random.nextInt(characters.length())) ));
        }
        // Add numbers
        useChars.add(random.nextInt(10)+"");
        useChars.add(random.nextInt(10)+"");
        useChars.add(random.nextInt(10)+"");
        Collections.shuffle(useChars);
        String randomString = StringUtils.join(useChars.toArray(), "").trim();
        randomString = randomString.substring(0, TOKEN_LENGHT);
        return Base64.encodeBase64String(randomString.getBytes());
	}
	
}
